export abstract class BaseState<T> {
    fsm: StateMachine<T>;
    name: string;
    abstract onEnter(...args);
    abstract onUpdate(dt);
    abstract onQuit();

}

export class StateMachine<T> {
    protected m_Owner: T
    
    protected _curState: BaseState<T>;
    protected _lastState:BaseState<T>;
    protected m_CurrentStateTime: number;
    protected isStop:boolean = false;
    public states: Map<string, BaseState<T>>;
     
    public constructor() {
        this.states = new Map<string, BaseState<T>>();
        this._curState = null;
    }
    public stop(){
        //this.states.clear();
        this.states = null;
        this._curState = null;
        this.isStop = true;
    }
    public run(stateName:string,...args) {
        let state = this.states.get(stateName);
        this._lastState = this._curState;
        this._curState = state;

        if (this._curState != null)
            this._curState.onEnter(...args);
        else {
            console.log('不可执行的状态');
        }
        this.m_CurrentStateTime = 0;
    }
    public get Onwer() {
        return this.m_Owner;
    }
    public set Onwer(onwer) {
        this.m_Owner = onwer;
    }
    public reduceState(stateName: string): boolean {
        return this.states.delete(stateName);
    }
    public addState(state: BaseState<T>) {
        if (!state)
            console.log("node = null");

        if (this.states.has(state.name) == false) {
            this.states.set(state.name, state);
        }
        else {
            console.log(`Node ${state.name} already existed`);
        }
    }
    public get CurrentStateTime() {
        return this.m_CurrentStateTime;
    }
    public backToLastState(){
        let state = this._curState;
        this._curState = this._lastState;
        this._lastState = state;
        this._curState.onEnter();
    }
    public changeState(stateName:string,...args) {
        this.m_CurrentStateTime = 0;
        let state = this.states.get(stateName);
        if (state == null) {
            //console.error(`Can not found node ${state.name}`);
            return;
        }
        if (this._curState && this._curState.onQuit) {
            this._curState.onQuit();
        }
        this._lastState = this._curState;
        this._curState = state;
        console.log(stateName);
        
        this._curState.onEnter(...args);
    }
    public update(dt) {
        if (this.isStop) {
            return;
        }
        this.m_CurrentStateTime += dt;
        if (this._curState && this._curState.onUpdate)
            this._curState.onUpdate(dt);
    }
}
